#include <qdir.h>
#include <iostream>
#include <map>
using namespace std;

#include <qapplication.h>
#include <qsqldatabase.h>
#include <qregexp.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#include <cdaudio.h>

#include "decoder.h"
#include "metadata.h"
#include "maddecoder.h"
#include "vorbisdecoder.h"
#include "playbackbox.h"
#include "globalsettings.h"
#include "ScanForAudio.h"
#include "AudioPlayer.h"

#include <mythtv/mythcontext.h>
#include <mythtv/mythplugin.h>
#include <mythtv/mythmedia.h>
#include <mythtv/mythdbcon.h>
#include <mythtv/lcddevice.h>

#include <mythtv/libmythui/myththemedmenu.h>

ScanForAudio*     m_FileScanner;
AudioPlayer*      m_AudioPlayer;

QValueVector<SelectionInfo>  SelectionItemList;
QValueVector<SelectionInfo>  PlaybackItemList;

QString m_AddAll       = "[Add All]";
QString m_MetaUnknown   = "<unknown>";
QString m_SchemaVersion = "1";

void startPlayback()
{
   PlaybackBoxMusic *pbb = new PlaybackBoxMusic
      (
         gContext->GetMainWindow(),
         "audio_select",
         "audio-",
         "audio_select",
         *m_AudioPlayer
      );
   m_AudioPlayer->SetHandler( pbb );
   qApp->unlock();
   pbb->exec();
   qApp->lock();

   pbb->stop();

   qApp->processEvents();

   m_AudioPlayer->ClearHandler();
   delete pbb;
}

void UpdateSchema()
{
   MSqlQuery query(MSqlQuery::InitCon());

   query.exec("DELETE FROM settings WHERE value='MythAudio.SchemaVersion';");
   query.exec(QString("INSERT INTO settings (value, data, hostname) "
                         "VALUES ('MythAudio.SchemaVersion', %1, NULL);")
                        .arg(m_SchemaVersion));

   // Brute force here
   query.exec("DROP TABLE audio_tracks;");
   m_FileScanner->Start();
}

void MusicCallback(void *, QString &selection)
{
   QString sel = selection.lower();

   printf( "Select %s\n", sel.ascii() );

   if( sel == "audio_select" )
   {
      //startPlayback(mdata->all_playlists, mdata->all_music);
   }
   else if( sel == "settings_scan" )
   {
//      if( "" != mdata->startdir )
//      {
//         //SearchDir(mdata->startdir);
//         //RebuildMusicTree(mdata);
//      }
   }
   else if( sel == "music_set_general" )
   {
      AudioGeneralSettings settings;
      settings.exec();
   }
   else if( sel == "music_set_player" )
   {
      AudioPlayerSettings settings;
      settings.exec();
   }
   else if( sel == "exiting_menu" )
   {
//      if( mdata->runPost )
//      {
//         postMusic();
//      }
//      delete mdata;
   }
}

void runMenu(QString which_menu)
{
   QString themedir = gContext->GetThemeDir();

   MythThemedMenu *diag = new MythThemedMenu(themedir.ascii(), which_menu,
                                             GetMythMainWindow()->GetMainStack(),
                                             "audio menu");

   printf( "runMenu 1\n" );

   diag->setCallback(MusicCallback, 0);
   diag->setKillable();

   if( diag->foundTheme() )
   {
      if( class LCD * lcd = LCD::Get() )
      {
         lcd->switchToTime();
      }
      GetMythMainWindow()->GetMainStack()->AddScreen(diag);
   }
   else
   {
      cerr << "Couldn't find theme " << themedir << endl;
      delete diag;
   }
}

extern "C" {
   int mythplugin_init(const char *libversion);
   void mythplugin_run(void);
   void mythplugin_config(void);
   void mythplugin_destroy(void);
}

void runMusicPlayback(void);
void runScan(void);

void handleMedia(MythMediaDevice *)
{
   if( gContext->GetNumSetting("AutoPlayCD", 0) )
   {
      runMusicPlayback();
   }
   else
   {
      mythplugin_run();
   }
}

void setupKeys(void)
{
   REG_JUMP("Play music",             "", "", runMusicPlayback);

   REG_KEY("Audio", "STOP",    "Stop playback",          "O");
   REG_KEY("Audio", "PAUSE",   "Pause/Restart playback", "P");
   REG_KEY("Audio", "PLAY",    "Start playback",         "Space");
   REG_KEY("Audio", "REWIND",  "Rewind",                 "(");
   REG_KEY("Audio", "FORWARD", "Fast Forward",           ")");
   REG_KEY("Audio", "REPLAY",  "Move to previous track", "Q");
   REG_KEY("Audio", "SKIP",    "Move to next track",     "Z");
   REG_KEY("Audio", "INFO",    "Information",            "I");
   REG_KEY("Audio", "SELECT",  "Select item",            "Enter");
   REG_KEY("Audio", "MENU",    "Display menu",           "M");

   REG_MEDIA_HANDLER("MythAudio Media Handler 1/2", "", "", handleMedia,
                     MEDIATYPE_AUDIO | MEDIATYPE_MIXED, QString::null);
   REG_MEDIA_HANDLER("MythAudio Media Handler 2/2", "", "", handleMedia,
                     MEDIATYPE_MMUSIC, "ogg,mp3,aac,flac");
}

int mythplugin_init(const char *libversion)
{
printf( "mythaudio::mythplugin_init\n" );
   if( !gContext->TestPopupVersion("mythaudio", libversion,
                                    MYTH_BINARY_VERSION) )
   {
      return -1;
   }

//   gContext->ActivateSettingsCache(false);
//   UpgradeMusicDatabaseSchema();
//   gContext->ActivateSettingsCache(true);

   AudioGeneralSettings general;
   general.load();
   general.save();
   AudioPlayerSettings settings;
   settings.load();
   settings.save();

   setupKeys();

   Decoder::SetLocationFormatUseTags();

   m_AudioPlayer = new AudioPlayer( PlaybackItemList );
   m_FileScanner = new ScanForAudio();

   QString schemaVersion = gContext->GetSetting("MythAudio.SchemaVersion");
   if( schemaVersion != m_SchemaVersion )
   {
      printf( "Schema changed\n" );
      UpdateSchema();
   }
   else
   {
      printf( "Schema unchanged\n" );
   }
                                              
   return 0;
}

void mythplugin_run(void)
{
printf( "mythaudio::mythplugin_run\n" );
   runMusicPlayback();
}

void mythplugin_config(void)
{
printf( "mythaudio::mythplugin_config\n" );
   Decoder::SetLocationFormatUseTags();

   runMenu("audio-settings.xml");
}

void mythplugin_destroy(void)
{
printf( "mythaudio::mythplugin_destroy\n" );
   if( m_AudioPlayer != 0 )
   {
      delete m_AudioPlayer;
   }
   if( m_FileScanner != 0 )
   {
      delete m_FileScanner;
   }
}

void runMusicPlayback(void)
{
printf( "mythaudio::runMusicPlayback\n" );
   gContext->addCurrentLocation("playmusic");
   startPlayback();
   gContext->removeCurrentLocation();
}
